package com.zheng.redpacket.server.serivce.Impl;

import com.zheng.redpacket.server.dto.RedPacketDto;
import com.zheng.redpacket.server.serivce.RedPacketHandlerService;
import com.zheng.redpacket.server.serivce.RedPacketService;
import com.zheng.redpacket.server.serivce.RedisService;
import com.zheng.redpacket.server.utils.RedPacketUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;

@Service
public class RedPacketServiceImpl implements RedPacketService {
    //日志
    private static final Logger LOGGER = LoggerFactory.getLogger(RedPacketServiceImpl.class);
    //存储到redis中的key前缀
    private static final String keyPrefix = "redis:red:packet";

    @Autowired
    private RedisService redisService;
    @Autowired
    private RedPacketHandlerService handlerService;

    @Override
    public String handOut(RedPacketDto dto) throws Exception {
        //判断参数合法性
        if (dto.getTotal() > 0 && dto.getAmount() >0) {
            //获取红包金额列表
            List<Integer> packets = RedPacketUtil.divideRedPacket(dto.getAmount(), dto.getTotal());
            //生成全局唯一标识:前缀+用户Id+：+当前时间戳
            String timestamp = String.valueOf(System.nanoTime());
            String redId = new StringBuffer(keyPrefix).append(dto.getUserId()).append(":").append(timestamp).toString();
            //随机金额放入缓存列表
            for (int i = 0; i < packets.size(); i++) {
                redisService.lPush(redId, packets.get(i));
            }
            //redisService.lPushAll(redId, packets);
            String redTotalKey = redId + ":total";
            redisService.set(redTotalKey, dto.getTotal());
            handlerService.recordRedPacket(dto, redId, packets);
            return redId;
        }else {
            throw new Exception("参数不合法");
        }
    }

    @Override
    public BigDecimal rod(Integer userId, String redId) throws Exception {
        //查询是否已抢过红包，若抢过直接返回金额
        Object obj = redisService.get(redId + userId + ":rob");
        if (obj != null){
            return new BigDecimal(obj.toString());
        }
        //判断红包个数是否大于0
        Boolean flag = click(redId);
        if (flag) {
            final String lockKey = redId+userId+"-lock";
            Boolean lock = redisService.setIfAbsent(lockKey, redId);
            Object value = redisService.rPop(redId);
            try {
                if (lock) {
                    if (value != null) {
                        String redTotal = redId+":total";
                        //抢到红包，当前红包数减一
                        Integer currentTotal = redisService.get(redTotal) != null ? (Integer) redisService.get(redTotal) : 0;
                        redisService.set(redTotal, currentTotal-1);
                        BigDecimal result = new BigDecimal(value.toString()).divide(new BigDecimal(100));
                        handlerService.recordRobRedPacket(userId, redId, new BigDecimal(value.toString()));
                        redisService.set(redId+userId+":rob", result, 24*60*60L);
                        LOGGER.info("{}用户抢到了{}红包，金额{}元",userId, redId, result);
                        return result;
                    }
                }
            } catch (Exception e) {
                throw new Exception("系统异常，加锁失败");
            }
        }
        return null;
    }

    /**
     * 判断是否有剩余红包，若有返回true，否则返回false
     * @param redId
     * @return
     */
    private Boolean click(String redId) throws Exception {
        String redTotal = redId+":total";
        Object total = redisService.get(redTotal);
        if (total != null && Integer.valueOf(total.toString()) > 0) {
            return true;
        }
        return false;
    }
}
